import hashlib

from gglib.packet import Packet
from gglib.settings import AUTHENTICATION_BACKENDS
from gglib import db
from gglib.user import User
from gglib.utils import import_attr


def login(session, user):
    session["_user"] = user
    user.session = session


def is_logged(session):
    return "_user" in session


def logout(session):
    user = session["_user"]
    delattr(user, "session")
    del session["_user"]


class AuthenticationBackend:
    def authenticate(self, session, username, password):
        user = db.get_user(username=username)
        if not user:
            return None
        user = User.manager.make_user(**user)
        md5_password = hashlib.md5((password + ":" + user.salt).encode("utf-8")).hexdigest()
        if md5_password == user.password:
            return user
    #
    # def get_user(self, user_id):
    #     return db.get_user(username=user_id)


# 实例化配置中所有的认证模块
_authentication_backends = [import_attr(a)() for a in AUTHENTICATION_BACKENDS]


# 装饰器，用于装饰登录成功后的请求处理函数
def login_required(method):
    def wrapper(session, packet):
        if not is_logged(session):
            pkt = Packet(packet)
            pkt.errcode = 1
            pkt.errmsg = "you must login first"
            session.route_packet(pkt)
            return

        return method(session, packet)

    return wrapper


# 使用认证模块进行认证，此方法类似于DJANGO中的认证系统
def authenticate(session, **kwargs):
    # 如果有一个认证模块返回一个用户对象则认为认证成功，则不继续调用余下的认证模块
    for backend in _authentication_backends:
        try:
            user = backend.authenticate(session, **kwargs)
            if user:
                return user
        except:
            continue
